home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / cli / StdIOHandler12.lha / StdIO-Handler / StdIO-Handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-06  |  12.0 KB  |  424 lines

  1. ;/* "C:Execute" me to compile me with SAS/C 6
  2. Set file StdIO-Handler
  3.  
  4. sc:c/sc MOD NOICON VERBOSE STRMERGE UNSCHAR NOSTKCHK IGNORE=73 MOD CSRC $file.c
  5. sc:c/slink NOICONS FROM $file.o TO $file LIB lib:amiga.lib,lib:sc.lib,lib:debug.lib VERBOSE SMALLCODE SMALLDATA NODEBUG
  6. makedoc $file.c AUTODOC $file.doc BEGIN "/**LL******" END "******" CONVERTCOMMENTS
  7. delete $file.o
  8. cd /
  9. lha -r a Release:StdIO-Handler_v1.2.lha StdIO-Handler
  10. UnSet file
  11. Quit
  12. */
  13.  
  14. /*
  15. ** $PROJECT: StdIO-Handler
  16. **
  17. ** $VER: StdIO-Handler.c 1.2 (05.04.95)
  18. **
  19. ** by
  20. **
  21. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  22. **
  23. ** (C) Copyright 1995
  24. ** All Rights Reserved !
  25. **
  26. ** $HISTORY:
  27. **
  28. ** 05.04.95 : 001.002 : now I get the Process from the MsgPort structure
  29. ** 17.01.95 : 001.001 : works fine I think, also async
  30. ** 16.01.95 : 000.001 : initial
  31. */
  32.  
  33. /*FS*/ /* $STARTDEFINE: "BumpRev defines"*/
  34. #define VERSION  1
  35. #define REVISION 2
  36. #define DATE "5.4.95"
  37. #define VERS "StdIO-Handler 1.2"
  38. #define VSTRING "StdIO-Handler 1.2 (5.4.95)\r\n"
  39. #define VERSTAG "\0$VER: StdIO-Handler 1.2 (5.4.95)"
  40. /*FE*/ /* $ENDDEFINE:   */
  41.  
  42. /*GB*** StdIO-Handler ********************************************************
  43.  
  44. $VER: StdIO-Handler.doc
  45.  
  46. NAME
  47.     StdIO-Handler - Handler for StdIO access
  48.  
  49. FUNCTION
  50.     In december 1994 I got a PIPE package and I was very supprised about the
  51.     easy implementation of these pipes. So I used this very often with gzip
  52.     and tar. But after some tries, to use the pipes with standard Amiga CLI
  53.     programs, I found no trick to redirect the input and output to the pipes.
  54.     At this point I had a idea of writing a transparent handler. Thus the
  55.     StdIO-Handler was born, using some example code from the Device-Handler
  56.     by Matthias Scheler and Marius Gröger (Thanks for the available code !).
  57.     The only thing you have to do, is to copy the STDIO file to your
  58.     Devs:DosDrivers/ directory and the handler to your L: directory.
  59.     After this you can use it like all other devices.
  60.     Note: If you use this handler with the pipes, you can't use tools, which
  61.           Seek's in the files (see the appropriate pipes doc) !
  62.  
  63.     Example Mount File :
  64.  
  65.     \* Standard-IO Handler *\
  66.     Handler     = L:StdIO-Handler
  67.     Stacksize   = 1000
  68.     Priority    = 5
  69.     GlobVec     = -1
  70.  
  71.  
  72. EXAMPLES
  73.     Output the current direcory in sorted order :
  74.     List | Sort Stdio: to Stdio:
  75.  
  76.     Output all files and subdirs last modified on august 1994 :
  77.     List ALL | search stdio: Aug-94 NONUM
  78.  
  79.     List ALL | search stdio: -s--rw-d NONUM
  80.  
  81. AUTHOR
  82.     Stefan Ruppert
  83.     Windthorststraße 5
  84.     65439 Flörsheim am Main
  85.     GERMANY
  86.     EMail: ruppert@vs3.informatik.fh-wiesbaden.de
  87.  
  88. ******************************************************************************
  89. *
  90. */
  91.  
  92. /*FS*/ /*"Includes"*/
  93. #include <exec/memory.h>
  94. #include <exec/execbase.h>
  95. #include <devices/trackdisk.h>
  96. #include <dos/dosextens.h>
  97. #include <dos/filehandler.h>
  98. #include <dos/dos.h>
  99.  
  100. #define __USE_SYSBASE 42
  101.  
  102. #include <clib/exec_protos.h>
  103. #include <pragmas/exec_pragmas.h>
  104.  
  105. #include <clib/dos_protos.h>
  106. #include <pragmas/dos_pragmas.h>
  107.  
  108. #include <clib/utility_protos.h>
  109. #include <pragmas/utility_pragmas.h>
  110.  
  111. #include <string.h>
  112.  
  113. #include <debug.h>
  114. #include <register.h>
  115. /*FE*/
  116.  
  117. /*FS*/ /*"Structures"*/
  118. typedef struct GlobalData {
  119.    struct Library *gd_SysBase;
  120.    struct Library *gd_DOSBase;
  121.    struct Library *gd_UtilityBase;
  122.    struct MsgPort *gd_Port;
  123.    struct MsgPort *gd_ReplyPort;
  124.    struct DosList *gd_DosList;
  125.    struct Process *gd_We;
  126. } *GD;
  127.  
  128. struct StdIOData
  129. {
  130.    struct StandardPacket Packet;
  131.    struct MsgPort *Handler;
  132.    struct DosPacket *Pkt;
  133.    BPTR StdIO;
  134. };
  135.  
  136. #define SysBase (gd->gd_SysBase)
  137. #define DOSBase (gd->gd_DOSBase)
  138. #define UtilityBase (gd->gd_UtilityBase)
  139. /*FE*/
  140.  
  141. /*FS*/ /*"entry()"*/
  142. static ULONG main(void);
  143. static RegCall GetA4 ULONG entry(REGA0 UBYTE *line,REGD0 ULONG len)
  144. {
  145.    return(main());
  146. }
  147. const static UBYTE version[]= VERSTAG;
  148. /*FE*/
  149.  
  150. /*FS*/ static struct DosPacket *WaitDosPacket(GD gd, struct MsgPort *port)
  151. {
  152.    WaitPort(port);
  153.    return (struct DosPacket *)(GetMsg(port)->mn_Node.ln_Name);
  154. }
  155. /*FE*/
  156. /*FS*/ static void ReplyDosPacket(GD gd, struct MsgPort *port, struct DosPacket *Packet,LONG Res1,LONG Res2)
  157. {
  158.    struct MsgPort *reply = Packet->dp_Port;
  159.  
  160.    ENTERING;
  161.  
  162.    Packet->dp_Port = port;
  163.    Packet->dp_Link->mn_Node.ln_Name = (char *)Packet;
  164.    Packet->dp_Res1 = Res1;
  165.    Packet->dp_Res2 = Res2;
  166.  
  167.    PutMsg (reply, Packet->dp_Link);
  168.  
  169.    LEAVING;
  170. }
  171. /*FE*/
  172.  
  173. /*FS*/ static void SendDosPacket(GD gd,struct DosPacket *Pkt)
  174. {
  175.    struct StdIOData *stdio = (struct StdIOData *) Pkt->dp_Arg1;
  176.  
  177.    ENTERING;
  178.  
  179.    stdio->Pkt = Pkt;
  180.  
  181.    stdio->Packet.sp_Pkt.dp_Port = gd->gd_ReplyPort;
  182.    stdio->Packet.sp_Pkt.dp_Res1 = 0;
  183.    stdio->Packet.sp_Pkt.dp_Res2 = 0;
  184.    stdio->Packet.sp_Pkt.dp_Arg2 = Pkt->dp_Arg2;
  185.    stdio->Packet.sp_Pkt.dp_Arg3 = Pkt->dp_Arg3;
  186.    PutMsg(stdio->Handler,&stdio->Packet.sp_Msg);
  187.  
  188.    LEAVING;
  189. }
  190. /*FE*/
  191.  
  192. /*FS*/ static BOOL openres(GD gd)
  193. {
  194.    BOOL rc = FALSE;
  195.  
  196.    DB(("entered\n"));
  197.  
  198.    DOSBase          =
  199.    UtilityBase      = NULL;
  200.  
  201.    gd->gd_Port      =
  202.    gd->gd_ReplyPort = NULL;
  203.  
  204.    if (SysBase->lib_Version >= 37)
  205.    {
  206.       if (DOSBase = OpenLibrary("dos.library", 37))
  207.       {
  208.          if (UtilityBase = OpenLibrary("utility.library", 37))
  209.          {
  210.             if (gd->gd_Port = CreateMsgPort())
  211.             {
  212.                if(gd->gd_ReplyPort = CreateMsgPort())
  213.                {
  214.                  rc = TRUE;
  215.                } else
  216.                   DB(("no reply port\n"));
  217.             }
  218.             else DB(("no device port\n"));
  219.          }
  220.          else DB(("no utility V37\n"));
  221.       }
  222.       else DB(("no dos V37\n"));
  223.    }
  224.    else DB(("no exec V37\n"));
  225.  
  226.    DB(("left: %ld\n",rc));
  227.  
  228.    return rc;
  229. }
  230. /*FE*/
  231. /*FS*/ static void closeres(GD gd)
  232. {
  233.    DB(("freeing port\n"));
  234.    if (gd->gd_Port) DeleteMsgPort(gd->gd_Port);
  235.  
  236.    if (gd->gd_ReplyPort) DeleteMsgPort(gd->gd_ReplyPort);
  237.  
  238.    DB(("closing dos\n"));
  239.    if (DOSBase) CloseLibrary(DOSBase);
  240.  
  241.    DB(("closing utility\n"));
  242.    if (UtilityBase) CloseLibrary(UtilityBase);
  243. }
  244. /*FE*/
  245.  
  246. /*FS*/ static ULONG main(void)
  247. {
  248.    struct GlobalData GlobalData;
  249.    struct GlobalData *gd;
  250.  
  251.    struct DosPacket *Pkt;
  252.    BOOL Done;
  253.    ULONG OpenCnt;
  254.  
  255.    gd = &GlobalData;
  256.  
  257.    DB(("Hello, this is the StdIO: Device\n"));
  258.  
  259.    SysBase = *(struct Library**)4L;
  260.  
  261.    if ((gd->gd_We = (struct Process *)FindTask(NULL))->pr_CLI) return RETURN_FAIL;
  262.  
  263.    DB(("waiting for startup-packet...\n"));
  264.    Pkt = WaitDosPacket(gd, &gd->gd_We->pr_MsgPort);
  265.  
  266.    if (openres(gd))
  267.    {
  268.       struct Process *proc;
  269.       struct FileHandle *fh;
  270.       struct StdIOData *retio;
  271.       ULONG portmask   = (1<<gd->gd_Port->mp_SigBit);
  272.       ULONG replymask  = (1<<gd->gd_ReplyPort->mp_SigBit);
  273.       ULONG recvd;
  274.  
  275.       gd->gd_DosList = (struct DosList *)BADDR(Pkt->dp_Arg3);
  276.       gd->gd_DosList->dol_Task = gd->gd_Port;
  277.  
  278.       DB(("replying startup-packet...\n"))
  279.       ReplyDosPacket(gd, gd->gd_Port, Pkt, DOSTRUE, Pkt->dp_Res2);
  280.  
  281.       Done=FALSE;
  282.       OpenCnt=0L;
  283.  
  284.       DB(("entering mainloop\n"));
  285.  
  286.       while (!Done)
  287.       {
  288.          recvd = Wait(portmask | replymask);
  289.  
  290.          if(recvd & replymask)
  291.          {
  292.             while((retio = (struct StdIOData *) GetMsg(gd->gd_ReplyPort)))
  293.             {
  294.                LONG Bytes = retio->Packet.sp_Pkt.dp_Res1;
  295.  
  296.                DB(("replied stdiodata : %lx , Pkt : %lx\n",retio,retio->Pkt));
  297.  
  298.                if (Bytes < 0L)
  299.                   ReplyDosPacket(gd, gd->gd_Port,retio->Pkt, -1, retio->Packet.sp_Pkt.dp_Res2);
  300.                else
  301.                   ReplyDosPacket(gd, gd->gd_Port,retio->Pkt, Bytes, 0);
  302.             }
  303.          }
  304.  
  305.          if(recvd & portmask)
  306.          {
  307.             struct Message *msg;
  308.  
  309.             while((msg = GetMsg(gd->gd_Port)))
  310.             {
  311.                Pkt = (struct DosPacket *) msg->mn_Node.ln_Name;
  312.                DB(("got packet %ld\n",Pkt->dp_Type));
  313.  
  314.                Pkt->dp_Res1 = DOSFALSE;
  315.                Pkt->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
  316.  
  317.                switch (Pkt->dp_Type)
  318.                {
  319.                case ACTION_FINDINPUT:
  320.                case ACTION_FINDOUTPUT:
  321.                   fh = BADDR(Pkt->dp_Arg1);
  322.                   fh->fh_Arg1 = 0L;
  323.  
  324.  
  325.                   proc = (struct Process *) Pkt->dp_Port->mp_SigTask;
  326.                   if((Pkt->dp_Port->mp_Flags == PA_SIGNAL) && (proc->pr_Task.tc_Node.ln_Type == NT_PROCESS))
  327.                   {
  328.                      struct StdIOData *stdio;
  329.                      if((stdio = AllocVec(sizeof(struct StdIOData),MEMF_ANY)))
  330.                      {
  331.                         if(Pkt->dp_Type == ACTION_FINDINPUT)
  332.                         {
  333.                            stdio->StdIO = proc->pr_CIS;
  334.                            stdio->Packet.sp_Pkt.dp_Type = ACTION_READ;
  335.                         } else
  336.                         {
  337.                            stdio->StdIO = proc->pr_COS;
  338.                            stdio->Packet.sp_Pkt.dp_Type = ACTION_WRITE;
  339.                         }
  340.                         fh  = BADDR(stdio->StdIO);
  341.                         stdio->Handler = fh->fh_Type;
  342.                         stdio->Packet.sp_Pkt.dp_Link          = &stdio->Packet.sp_Msg;
  343.                         stdio->Packet.sp_Pkt.dp_Arg1          = fh->fh_Arg1;
  344.                         stdio->Packet.sp_Msg.mn_Node.ln_Name  = (STRPTR)&stdio->Packet.sp_Pkt;
  345.                         stdio->Packet.sp_Msg.mn_Node.ln_Type  = NT_MESSAGE;
  346.                         stdio->Packet.sp_Msg.mn_Length        = sizeof(struct StandardPacket);
  347.                         stdio->Packet.sp_Msg.mn_ReplyPort     = gd->gd_ReplyPort;
  348.  
  349.                         fh = BADDR(Pkt->dp_Arg1);
  350.                         fh->fh_Arg1 = (LONG) stdio;
  351.  
  352.                         DB(("process : %s , stdio : %lx , type %ld \n",proc->pr_Task.tc_Node.ln_Name,stdio->StdIO,stdio->Packet.sp_Pkt.dp_Type));
  353.                         OpenCnt++;
  354.                         ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSTRUE, 0);
  355.                      } else
  356.                         ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_NO_FREE_STORE);
  357.                   } else
  358.                      ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_OBJECT_NOT_FOUND);
  359.                   break;
  360.                case ACTION_END:
  361.                   {
  362.                      struct StdIOData *stdio = (struct StdIOData *) Pkt->dp_Arg1;
  363.  
  364.                      if(stdio)
  365.                      {
  366.                         OpenCnt--;
  367.                         FreeVec(stdio);
  368.                         ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSTRUE, 0);
  369.                      }
  370.                   }
  371.                   break;
  372.                case ACTION_WRITE:
  373.                case ACTION_READ:
  374.                   {
  375.                      struct StdIOData *stdio = (struct StdIOData *)Pkt->dp_Arg1;
  376.  
  377.                      if(stdio && stdio->Packet.sp_Pkt.dp_Type == Pkt->dp_Type)
  378.                         SendDosPacket(gd,Pkt);
  379.                   }
  380.                   break;
  381.                case ACTION_IS_FILESYSTEM:
  382.                   ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE, 0);
  383.                   break;
  384.                case ACTION_SEEK:
  385.                case ACTION_SET_FILE_SIZE:
  386.                   ReplyDosPacket(gd, gd->gd_Port,Pkt, -1,ERROR_ACTION_NOT_KNOWN);
  387.                   break;
  388.                case ACTION_DIE:
  389.                   DB(("opencnt = %ld\n",OpenCnt));
  390.  
  391.                   if (OpenCnt==0L)
  392.                   {
  393.                      if (IsListEmpty(&gd->gd_Port->mp_MsgList))
  394.                      {
  395.                         gd->gd_DosList->dol_Task = NULL;
  396.  
  397.                         ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSTRUE, 0);
  398.  
  399.                         Done=TRUE;
  400.                      }
  401.                      else ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_OBJECT_IN_USE);
  402.                   }
  403.                   else ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_OBJECT_IN_USE);
  404.                   break;
  405.                default:
  406.                   ReplyDosPacket(gd, gd->gd_Port, Pkt, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  407.                   break;
  408.                }
  409.             }
  410.          }
  411.       }
  412.    }
  413.    else
  414.       ReplyDosPacket(gd, &gd->gd_We->pr_MsgPort, Pkt, DOSFALSE, ERROR_NO_FREE_STORE);
  415.  
  416.    closeres(gd);
  417.  
  418.    DB(("returning\n"));
  419.  
  420.    return(RETURN_OK);
  421. }
  422. /*FE*/
  423.  
  424.